#include "Palette/RIVIAPaletteMgr.h"
#include <QImage>

RIVIAPaletteMgr* RIVIAPaletteMgr::m_pInstance = nullptr;
QMutex RIVIAPaletteMgr::m_lockMutex;

RIVIAPaletteMgr *RIVIAPaletteMgr::getInstance()
{
    if (nullptr == m_pInstance)
    {
        QMutexLocker oLocker(&m_lockMutex);
        {
            if (nullptr == m_pInstance)
            {
                m_pInstance = new RIVIAPaletteMgr();
            }
        }
    }
    return m_pInstance;
}

void RIVIAPaletteMgr::freeInstance()
{
    if (nullptr != m_pInstance)
    {
        QMutexLocker oLocker(&m_lockMutex);
        {
            if (nullptr != m_pInstance)
            {
                delete m_pInstance;
                m_pInstance = nullptr;
            }
        }
    }
}

RIVIAPaletteMgr::RIVIAPaletteMgr()
{
    m_MainPalette.create(256, 256, CV_8UC3);
    m_SidePalette.create(256, 256, CV_8UC3);
    m_CurColor.resize(3);
    m_CurColor[0] = 0;
    m_CurColor[1] = 0;
    m_CurColor[2] = 0;

    m_CurBackColor.resize(3);
    m_CurBackColor[0] = 255;
    m_CurBackColor[1] = 255;
    m_CurBackColor[2] = 255;
}

RIVIAPaletteMgr::~RIVIAPaletteMgr()
{

}

void RIVIAPaletteMgr::setMainPalette(int channel, int degree)
{
    int nRows = m_MainPalette.rows;
    int nCols = m_MainPalette.cols;

    cv::MatIterator_<cv::Vec3b> it = m_MainPalette.begin<cv::Vec3b>();

    switch(channel)
    {
    case 0: //Fixed R channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = j;
                (*it)[1] = i;
                (*it)[2] = degree;
                ++it;
            }
        }
        break;
    case 1: //Fixed G channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = j;
                (*it)[1] = degree;
                (*it)[2] = i;
                ++it;
            }
        }
        break;
    case 2: //Fixed B channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = degree;
                (*it)[1] = j;
                (*it)[2] = i;
                ++it;
            }
        }
        break;
    }
}

void RIVIAPaletteMgr::setSidePalette(int channel)
{
    int nRows = m_SidePalette.rows;
    int nCols = m_SidePalette.cols;

    cv::MatIterator_<cv::Vec3b> it = m_SidePalette.begin<cv::Vec3b>();

    switch(channel)
    {
    case 0://Fixed R channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = 0;
                (*it)[1] = 0;
                (*it)[2] = i;
                ++it;
            }
        }
        break;
    case 1://Fixed G channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = 0;
                (*it)[1] = i;
                (*it)[2] = 0;
                ++it;
            }
        }
        break;
    case 2://Fixed B channel
        for(int i = 0; i < nRows; i++)
        {
            for(int j = 0; j < nCols; j++)
            {
                (*it)[0] = i;
                (*it)[1] = 0;
                (*it)[2] = 0;
                ++it;
            }
        }
        break;
    }
}

QImage RIVIAPaletteMgr::getMainQImage()
{
    return QImage((const uchar*)(m_MainPalette.data), m_MainPalette.cols, m_MainPalette.rows, QImage::Format_RGB888).rgbSwapped();
}

QImage RIVIAPaletteMgr::getSideQImage()
{
    return QImage((const uchar*)(m_SidePalette.data), m_SidePalette.cols, m_SidePalette.rows, QImage::Format_RGB888).rgbSwapped();
}

void RIVIAPaletteMgr::setCurColor(int r, int g, int b)
{
    m_CurColor[0] = r;
    m_CurColor[1] = g;
    m_CurColor[2] = b;
}

void RIVIAPaletteMgr::setCurBackColor(int r, int g, int b)
{
    m_CurBackColor[0] = r;
    m_CurBackColor[1] = g;
    m_CurBackColor[2] = b;
}

QVector<int> RIVIAPaletteMgr::getCurColor() const
{
    return m_CurColor;
}

QVector<int> RIVIAPaletteMgr::getCurBackColor() const
{
    return m_CurBackColor;
}
